#pragma once
#include ".\tricell.h"
#include <cmath>

#ifndef SMALL
#define SMALL 1.0e-12 //无穷小
#endif

#ifndef INF
#define INF 1.0e+20 //无穷大
#endif

TriCell::TriCell()
{
	int i, j;
	for (i = 0; i < 3; i++)
	{
		this->node[i] = 0;
		this->dSurfNormal[i] = 0;
		for (j = 0; j < 3; j++)
			this->Coord[i][j] = 0.0;
	}
	this->iSurfType = 0;
	this->dCellArea = 0.0;
	this->_zone_no = 0;
}

TriCell::TriCell(double pp[3][3], int size)
{
	int i, j;
	for (i = 0; i < size; i++)
	{
		this->node[i] = 0;
		this->dSurfNormal[i] = 0;
		for (j = 0; j < 3; j++)
			this->Coord[i][j] = pp[i][j];
	}
	//this->no = 0;
	this->iSurfType = 0;
	this->dCellArea = 0.0;
	this->_zone_no = 0;
}

void TriCell::AreaNorm(void)
{
	double tmp[3], ab[3], ac[3], ovtmp;
	int i;
	for (i = 0; i < 3; i++)
	{
		ab[i] = Coord[1][i] - Coord[0][i];
		ac[i] = Coord[2][i] - Coord[0][i];
	}
	tmp[0] = ab[1] * ac[2] - ab[2] * ac[1];
	tmp[1] = ab[2] * ac[0] - ab[0] * ac[2];
	tmp[2] = ab[0] * ac[1] - ab[1] * ac[0];

	ovtmp = sqrt(tmp[0] * tmp[0] + tmp[1] * tmp[1] + tmp[2] * tmp[2]);
	for (i = 0; i < 3; i++)
		dSurfNormal[i] = tmp[i] / ovtmp;
	this->dCellArea = ovtmp / 2.0;
}

void TriCell::GetCoord(double coord[][3], int size)
{
	for (int i = 0; i < size; i++)
		for (int j = 0; j < 3; j++)
			coord[i][j] = this->Coord[i][j];
}

void TriCell::SetNo(int no)
{
	this->no = no;
}

int TriCell::GetNo()
{
	return this->no;
}

void TriCell::GetSN(double *dSN, int size)
{
	for (int i = 0; i < size; i++)
		dSN[i] = this->dSurfNormal[i];
}

void TriCell::SetNode(int* node, int size)
{
	for (int i = 0; i < size; i++)
		this->node[i] = node[i];
}

void TriCell::SetCoord(double coord[][3], int size)
{
	for (int i = 0; i < size; i++)
		for (int j = 0; j < 3; j++)
			this->Coord[i][j] = coord[i][j];
}

double TriCell::GetArea(void)
{
	return this->dCellArea;
}


void TriCell::GetNode(int node[], int size)
{
	for (int i = 0; i < size; i++)
		node[i] = this->node[i];
}


double Triangle_Intersect(TriCell *objCell, double pos[3], double vec[3], bool isRayFromOutside)
{
	int i;
	double t, rp1, rp2;
	double ab[3], ac[3], w[3];
	double tmp1, tmp2, postmp[3];
	double uu, uv, vv, wu, wv, rd;
	double dSN[3];
	double Coord[3][3];

	objCell->GetSN(dSN, 3);
	objCell->GetCoord(Coord, 3);

	t = INF;

	tmp1 = dSN[0] * vec[0] + dSN[1] * vec[1] + dSN[2] * vec[2];
	if (tmp1 >= 0.0)
	{
		if (isRayFromOutside)
			return t;
		else
		{
			dSN[0] = -dSN[0];
			dSN[1] = -dSN[1];
			dSN[2] = -dSN[2];
			tmp1 = -tmp1;
		}
	}

	if (tmp1 < 0.0)
	{
		tmp2 = dSN[0] * (Coord[0][0] - pos[0]) + dSN[1] * (Coord[0][1] - pos[1]) + dSN[2] * (Coord[0][2] - pos[2]);
		tmp2 = tmp2 / tmp1;
		if (tmp2 > 0.0)
		{
			for (i = 0; i < 3; i++)
			{
				postmp[i] = vec[i] * tmp2 + pos[i];
				ab[i] = Coord[1][i] - Coord[0][i];
				ac[i] = Coord[2][i] - Coord[0][i];
				w[i] = postmp[i] - Coord[0][i];
			}
			uu = ab[0] * ab[0] + ab[1] * ab[1] + ab[2] * ab[2];
			uv = ab[0] * ac[0] + ab[1] * ac[1] + ab[2] * ac[2];
			vv = ac[0] * ac[0] + ac[1] * ac[1] + ac[2] * ac[2];
			wu = w[0] * ab[0] + w[1] * ab[1] + w[2] * ab[2];
			wv = w[0] * ac[0] + w[1] * ac[1] + w[2] * ac[2];
			rd = uv * uv - uu * vv + SMALL;
			rp1 = (uv * wv - vv * wu) / rd;
			rp2 = (uv * wu - uu * wv) / rd;
			if (rp1 >= 0.0 && rp1 <= 1.0 && rp2 >= 0.0 && rp1 + rp2 <= 1.0)
				if (tmp2 < t)
				{
					t = tmp2;
				}
		}
	}

	return t;
}